use core::marker::PhantomData;
use embedded_hal::digital::{InputPin, OutputPin};
use super::SmileDelay;

// 延时需要 50ns 
pub struct HC165 <PL, CLK, Q7, DELAY> {
    pl: PL,
    q7: Q7,
    clk: CLK,
    _p: PhantomData<DELAY>,
}

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<PL, CLK, Q7> {
    PLErr(PL),
    CLKErr(CLK),
    Q7Err(Q7),
}

impl <PL, CLK, Q7, DELAY> HC165<PL, CLK, Q7, DELAY> 
    where PL: OutputPin,
        CLK: OutputPin,
        Q7: InputPin,
        DELAY: SmileDelay
{
    pub const fn new(pl: PL, clk: CLK, q7: Q7) -> Self {
        Self { pl, q7, clk, _p: PhantomData {} }
    }

    pub fn read_byte(&mut self) -> Result<u8, Error<PL::Error, CLK::Error, Q7::Error>>  {
        let mut value = 0u8;

        self.pl.set_low().map_err(Error::PLErr)?;
        DELAY::delay();
        self.pl.set_high().map_err(Error::PLErr)?;

        for _ in 0..8 {
            self.clk.set_high().map_err(Error::CLKErr)?;
            DELAY::delay();
            value <<= 1;
            if self.q7.is_high().map_err(Error::Q7Err)? {
                value |= 0x01;
            }
            self.clk.set_low().map_err(Error::CLKErr)?;
            DELAY::delay();
        }
        Ok(value)
    }
}




